﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ObjectCache.Tokens;
using System.Threading;

namespace ObjectCache.Test
{
    /// <summary>
    /// Summary description for UseCacheTest
    /// </summary>
    [TestClass]
    public class UseCacheTest
    {
        public UseCacheTest()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void GetSimpleValue()
        {
            var value = CacheManager.Instance.GetCache<int, string>().GetValueByID(1);
            Assert.AreEqual(null, value);
        }

        [TestMethod]
        public void TestResetFilter()
        {
            var cache = CacheManager.Instance.GetCache<string, string>();
            var name = cache.GetValueByID("hello", (long)CacheResetFilter.Normal, () => "John");

            Assert.AreEqual(name, "John");

            cache.Reset();

            Assert.AreEqual(cache.Count(), 0);

            name = cache.GetValueByID("hello", (long)CacheResetFilter.Normal, () => "Sue");

            cache.Reset();

            Assert.AreEqual(cache.Count(), 1);

            CacheManager.Instance.ResetCaches((long)CacheResetFilter.Normal);

            Assert.AreEqual(0, cache.Count());
        }

        [TestMethod]
        public void TestInstanceToken()
        {
            object instance = new object();

            var cache = CacheManager.Instance.GetCache<string, string>();

            var name = cache.GetValueByID("#1",
                () => "John", new InstanceToken(instance));

            Assert.AreEqual("John", name);

            instance = null;
            GC.Collect();

            Thread.Sleep(1000);

            name = cache.GetValueByID("#1");
            Assert.IsNull(name);
            Assert.AreEqual(0, cache.Count());
        }

        [TestMethod]
        public void TestSlideToken()
        {
            var cache = CacheManager.Instance.GetCache<string, string>();

            var name = cache.GetValueByID("#1",
                () => "John",
                new SlideTimeToken(2));

            Thread.Sleep(1000);

            name = cache.GetValueByID("#1");
            Assert.AreEqual("John", name);

            Thread.Sleep(1000);

            name = cache.GetValueByID("#1");
            Assert.AreEqual("John", name);

            Thread.Sleep(1000);

            name = cache.GetValueByID("#1");
            Assert.AreEqual("John", name);

            Thread.Sleep(3000);

            name = cache.GetValueByID("#1");
            Assert.AreEqual(null, name);
            
        }

        [TestMethod]
        public void TestAbsoluteToken()
        {
            var cache = CacheManager.Instance.GetCache<string, string>();

            var name = cache.GetValueByID("#1",
                () => "John",
                new AbsoluteTimeToken(2));

            name = cache.Get("#1");
            Assert.AreEqual("John", name);

            Thread.Sleep(1000);

            name = cache.Get("#1");
            Assert.AreEqual("John", name);

            Thread.Sleep(500);

            name = cache.Get("#1");
            Assert.AreEqual("John", name);

            Thread.Sleep(1000);

            name = cache.Get("#1");
            Assert.AreEqual(null, name);
        }

        [TestMethod]
        public void TestCacheWithNormalObjectToken()
        {
            var obj = new CacheConsumer("hello");

            Assert.AreEqual("hello", obj.TestField);

            var obj1 = new CacheConsumer("hello1");

            Assert.AreEqual("hello", obj1.TestField);

            obj = null;
            obj1 = null;
            GC.Collect();
            Thread.Sleep(4000);

            var obj2 = new CacheConsumer("hello2");

            Assert.AreEqual("hello2", obj2.TestField);

        }

        [TestMethod]
        public void TestCacheWithFormToken()
        {
            CacheForm form = new CacheForm();
            form.ShowDialog();

            Thread.Sleep(5000);

            var cache = CacheManager.Instance.GetCache<int, string>();

            Assert.AreEqual(0, cache.Count());
        }
    }

    internal class CacheConsumer
    {
        public string TestField;
        public CacheConsumer(string testStr)
        {
            TestField = CacheManager.Instance.GetCache<int, string>().GetWithCreate(0, () => testStr, new InstanceToken(this));
        }
    }

    public static class UseCacheHelper
    {
        public static string GetValueByID(this ICache<int, string> cache,
            int id)
        {
            return cache.Get(id);
        }

        public static string GetValueByID(this ICache<string, string> cache,
            string name, long resetfilter, Func<string> getDataAction)
        {
            return cache.GetWithCreate(name,
                getDataAction,
                new BaseToken());
        }

        public static string GetValueByID(this ICache<string, string> cache,
            string name, Func<string> getDataAction, BaseToken token)
        {
            return cache.GetWithCreate(name, getDataAction, token);
        }

        public static string GetValueByID(this ICache<string, string> cache,
            string name)
        {
            return cache.Get(name);
        }

       
    }

    [Flags]
    enum CacheResetFilter
    { 
        Normal = 1,
        Logic1 = 2,
        Logic2 = 4,
        Logic3 = 8
    }

 
}
